package com.ideal.manage.esms.service.project;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ideal.manage.esms.bean.DTO.Arithmetic;
import com.ideal.manage.esms.bean.DTO.PageDto;
import com.ideal.manage.esms.bean.project.ArithmeticDeployManage;
import com.ideal.manage.esms.bean.project.ArithmeticManage;
import com.ideal.manage.esms.bean.project.EquipmentManage;
import com.ideal.manage.esms.bean.project.ProjectManage;
import com.ideal.manage.esms.bean.sys.User;
import com.ideal.manage.esms.config.shiro.MyShiroRealm;
import com.ideal.manage.esms.repository.framework.MySpecification;
import com.ideal.manage.esms.repository.framework.SpecificationOperator;
import com.ideal.manage.esms.repository.programme.ArithmeticDeployManageRepository;
import com.ideal.manage.esms.repository.programme.ArithmeticManageRepository;
import com.ideal.manage.esms.repository.project.ProjectManageRepository;
import com.ideal.manage.esms.repository.system.UserProjectRepository;
import com.ideal.manage.esms.repository.system.UserRepository;
import com.ideal.manage.esms.util.HttpRequests;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * Created by 83730 on 2018/4/24.
 */
@Service
@CacheConfig(cacheNames = "arithmeticManageCache")
public class ArithmeticManageService {

    @Autowired
    private ArithmeticManageRepository arithmeticManageRepository;

    @Autowired
    private ArithmeticDeployManageRepository arithmeticDeployManageRepository;

    @Autowired
    private EquipmentManageService equipmentManageService;

    @Autowired
    private ProjectManageService projectManageService;

    @Autowired
    private ProjectManageRepository projectManageRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private UserProjectRepository userProjectRepository;

    @Value("${arithmeticFile.path}")
    private String arithmeticPath;

    /**
     * 分页 根据创建时间排序
     *
     * @param pageNum
     * @return
     */
    public Page<ArithmeticManage> findAllManages(int pageNum, HttpServletRequest request) {
        List<SpecificationOperator> operators = HttpRequests.getParametersStartingWith(request, "Q_");
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        SpecificationOperator operator = new SpecificationOperator("isValid", "1", "EQ");
        operators.add(operator);
        MySpecification<ArithmeticManage> mySpecifications = new MySpecification<>(operators);
        Pageable pageable = new PageRequest(pageNum, 15, sort);
        Page<ArithmeticManage> page = arithmeticManageRepository.findAll(mySpecifications, pageable);
        return page;
    }

    /**
     * 用于将文件上传到服务器
     *
     * @param path
     * @param file
     * @param pictureName
     */
    public void uploadFile(String path, MultipartFile file, String pictureName) {
        try {
            FileUtils.copyInputStreamToFile(file.getInputStream(), new File(path, pictureName));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除服务器已有的文件
     *
     * @param pathname
     */
    public void deleteFile(String pathname) {

        File oldFile = new File(pathname);
        if (oldFile.exists()) {
            oldFile.delete();
        }
    }

    /**
     * 算法管理-算法管理-保存算法
     *
     * @param id
     * @param name
     * @param objName
     * @param version
     * @param remark
     * @param inParameter
     * @param outParameter
     * @param isReverseControl
     * @param touchCondition
     * @param touchExpression
     * @param file
     * @param fileName
     */
    public void saveManage(String id, String name, Integer objName, String version, String remark, String inParameter, String outParameter, String outParameterName,
                           Integer isReverseControl, String touchCondition, String touchExpression, MultipartFile file, String fileName) {
        MyShiroRealm.ShiroUser shiroUser = (MyShiroRealm.ShiroUser) SecurityUtils.getSubject().getPrincipal();
        Date date = new Date();
        ArithmeticManage arithmeticManage = new ArithmeticManage();
        String uploadPath = "";
        String ftpUrl = null;
        String timeStr = String.valueOf(System.currentTimeMillis());
        if ("".equals(remark)) {
            remark = null;
        }
        if (id != null) {
            if (!StringUtils.isBlank(fileName) && file != null) {
                arithmeticManage = arithmeticManageRepository.findOne(id);
                //删除原有的文件
                deleteFile(arithmeticManage.getFtpUrl());
                //重新上传文件到项目所在服务器
                File dir = new File(arithmeticPath);
                if (!dir.exists()){
                    dir.mkdirs();
                }
                File newFile = new File(arithmeticPath +File.separator+ timeStr+ fileName);

                try {
                    file.transferTo(newFile);
                } catch (IOException e) {
                    e.printStackTrace();
                }

                ftpUrl = arithmeticPath +File.separator+ timeStr + fileName;
            }
            if (isReverseControl == null) {
                isReverseControl = 0;
            }
            arithmeticManage = findById(id);
            arithmeticManage.setName(name);
            arithmeticManage.setVersion(version);
            arithmeticManage.setRemark(remark);
            arithmeticManage.setObjName(objName);
            arithmeticManage.setInParameter(inParameter);
            arithmeticManage.setOutParameter(outParameter);
            arithmeticManage.setOutParameterName(outParameterName);
            arithmeticManage.setTouchCondition(touchCondition);
            arithmeticManage.setTouchExpression(touchExpression);
            arithmeticManage.setIsReverseControl(isReverseControl);
            arithmeticManage.setFtpUrl(ftpUrl);

            arithmeticManage.setUpdateTime(date);
        } else {
            //上传到项目所在服务器
            if (!StringUtils.isBlank(fileName) && file != null) {
                File dir = new File(arithmeticPath);
                if (!dir.exists()){
                    dir.mkdirs();
                }
                File newFile = new File(arithmeticPath+File.separator + timeStr+ fileName);

                try {
                    file.transferTo(newFile);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                ftpUrl = arithmeticPath +File.separator+ timeStr + fileName;
            }

            arithmeticManage.setName(name);
            arithmeticManage.setVersion(version);
            arithmeticManage.setIsValid(1);
            arithmeticManage.setRemark(remark);
            arithmeticManage.setObjName(objName);
            arithmeticManage.setInParameter(inParameter);
            arithmeticManage.setOutParameter(outParameter);
            arithmeticManage.setOutParameterName(outParameterName);
            arithmeticManage.setTouchCondition(touchCondition);
            arithmeticManage.setTouchExpression(touchExpression);
            arithmeticManage.setIsReverseControl(isReverseControl);
            arithmeticManage.setFtpUrl(ftpUrl);
            arithmeticManage.setImportTime(date);
            arithmeticManage.setCreateTime(date);
            arithmeticManage.setCreateUser(new User(shiroUser.getId()));
        }
        arithmeticManageRepository.save(arithmeticManage);
    }

    /**
     * 根据id找到相应算法
     *
     * @param id
     * @return
     */
    public ArithmeticManage findById(String id) {
        ArithmeticManage arithmeticManage = arithmeticManageRepository.findOne(id);
        return arithmeticManage;
    }

    /**
     * 批量删除算法
     *
     * @param ids
     */
    public void delManage(String[] ids) {
        List<ArithmeticManage> arithmeticManages = arithmeticManageRepository.findAll(Arrays.asList(ids));
        for (ArithmeticManage arithmeticManage : arithmeticManages) {
            arithmeticManage.setIsValid(0);
        }
        arithmeticManageRepository.save(arithmeticManages);
    }

    /**
     * 算法部署-选择算法-下拉框多选数据
     *
     * @return
     */
    public List<Arithmetic> findArithmetics() {
        List<ArithmeticManage> arithmeticManages = arithmeticManageRepository.findManages();
        List<Arithmetic> arithmetics = new ArrayList<>();
        for (ArithmeticManage arithmeticManage : arithmeticManages) {
            Arithmetic arithmetic = new Arithmetic();
            arithmetic.setId(arithmeticManage.getId());
            arithmetic.setText(arithmeticManage.getName());
            arithmetics.add(arithmetic);
        }
        return arithmetics;
    }

    /**
     * 找到所有的算法
     *
     * @return
     */
    public List<ArithmeticManage> findManages() {
        List<ArithmeticManage> arithmeticManages = arithmeticManageRepository.findManages();
        return arithmeticManages;
    }

    /**
     * 根据用户权限返回项目
     *
     * @param pageNum
     * @return
     */

    public PageDto findAllDeployManages(int pageNum, HttpServletRequest request) {
        List<ProjectManage> projectManagesList = new ArrayList<>();
        //获取当前登录用户
        MyShiroRealm.ShiroUser shiroUser = (MyShiroRealm.ShiroUser) SecurityUtils.getSubject().getPrincipal();
        User user = userRepository.findOne(shiroUser.getId());
        projectManagesList = userProjectRepository.findProjectByUser(user);

        //获取该页面下所有的项目
        Sort sort = new Sort(Sort.Direction.DESC, "updateTime");
        List<SpecificationOperator> operators = new ArrayList<SpecificationOperator>() {{
            add(new SpecificationOperator("isValid", "1", "EQ"));       //存在
        }};

        MySpecification<ProjectManage> mySpecifications = new MySpecification<>(operators);
        Pageable pageable = new PageRequest(pageNum, 15, sort);
        Page<ProjectManage> page = projectManageRepository.findAll(mySpecifications, pageable);
        // 设置PageDto
        List<ProjectManage> projectManages = page.getContent();
        //找到该页面项目下的所有设备
        List<EquipmentManage> oneList = new ArrayList<EquipmentManage>();
        for (ProjectManage projectManage : projectManages) {
            oneList.addAll(equipmentManageService.findByProjectId(projectManage.getId()));
        }
        //根据设备id找到所有的算法部署内容
        List<ArithmeticDeployManage> arithmeticDeployManages = new ArrayList<>();
        for (EquipmentManage equipmentManage : oneList) {
            arithmeticDeployManages.addAll(arithmeticDeployManageRepository.findByEquipmentId(equipmentManage.getId()));
        }
        //将所有的算法内容添加到项目中去
        for (ProjectManage projectManage : projectManages) {
            String arithmeticStr = "";
            Date arithmeticTime = null;
            for (ArithmeticDeployManage arithmeticDeployManage : arithmeticDeployManages) {

                if (arithmeticDeployManage.getEquipmentId().getProject().getId().equals(projectManage.getId())) {
                    if (arithmeticStr.contains(arithmeticDeployManage.getArithmeticId().getName())) {

                    } else {
                        arithmeticStr += arithmeticDeployManage.getArithmeticId().getName() + "|";
                    }
                    arithmeticTime = arithmeticDeployManage.getUpdateTime();
                }
            }
            if (arithmeticStr.contains("|")) {
                arithmeticStr = arithmeticStr.substring(0, arithmeticStr.lastIndexOf("|"));
            }
            if ("".equals(arithmeticStr)) {
                arithmeticStr = "未配置";
            }

            projectManage.setArithmeticStr(arithmeticStr);
        }
        long total = page.getTotalElements();
        PageDto pageDto = new PageDto();
        pageDto.setRows(projectManages);
        pageDto.setTotal(total);
        return pageDto;
    }

    /**
     * 找到所有的算法部署数据
     *
     * @return
     */
    public List<ArithmeticDeployManage> findAllDeployManages() {
        List<ArithmeticDeployManage> arithmeticDeployManages = arithmeticDeployManageRepository.findDeployManages();
        return arithmeticDeployManages;
    }

    /**
     * 保存部署算法
     * 算法管理 - 算法部署 - 新增
     *
     * @param source
     */
    public void saveArithmeticDeploy(String source) {
        MyShiroRealm.ShiroUser shiroUser = (MyShiroRealm.ShiroUser) SecurityUtils.getSubject().getPrincipal();
        JSONArray jsonArray = JSONArray.parseArray(source);
        Date date = new Date();
        List<ArithmeticDeployManage> arithmeticDeployManages = new ArrayList<>();
        Set<ProjectManage> projectManages = new HashSet<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            String equipment_id = jsonObject.getString("equipment_id");
            EquipmentManage equipmentManage = equipmentManageService.findOneById(equipment_id);
            projectManages.add(equipmentManage.getProject());
            String manage_id = jsonObject.getString("manage_id");

            ArithmeticDeployManage arithmeticDeployManage1 = new ArithmeticDeployManage();
            arithmeticDeployManage1.setEquipmentId(equipmentManage);
            arithmeticDeployManage1.setArithmeticId(arithmeticManageRepository.findOne(manage_id));
            arithmeticDeployManage1.setCreateTime(date);
            arithmeticDeployManage1.setUpdateTime(date);
            arithmeticDeployManage1.setCreateUser(new User(shiroUser.getId()));
            arithmeticDeployManage1.setIsValid(1);
            arithmeticDeployManages.add(arithmeticDeployManage1);

        }
        arithmeticDeployManageRepository.save(arithmeticDeployManages);
        //保存每次项目部署时间
        for (ProjectManage projectManage : projectManages) {
            projectManage.setDeployTime(date);
            projectManageRepository.save(projectManage);
        }
    }

    /**
     * 删除部署算法
     * 算法管理 - 算法部署 - 删除
     *
     * @param ids
     */
    public void delDeployManages(String[] ids) {
        List<ProjectManage> projectManages = projectManageRepository.findAll(Arrays.asList(ids));
        for (ProjectManage projectManage : projectManages) {
            List<EquipmentManage> equipmentManages = equipmentManageService.findByProjectId(projectManage.getId());
            for (EquipmentManage equipmentManage : equipmentManages) {
                List<ArithmeticDeployManage> deployManages = arithmeticDeployManageRepository.findByEquipmentId(equipmentManage.getId());
                for (ArithmeticDeployManage arithmeticDeployManage : deployManages) {
                    arithmeticDeployManage.setIsValid(0);
                }
                arithmeticDeployManageRepository.save(deployManages);
            }
        }
    }

    /**
     * 根据设备id找到算法部署数据
     *
     * @param equipmentId
     * @return
     */
    public List<ArithmeticDeployManage> findByEquipmentId(String equipmentId) {
        List<ArithmeticDeployManage> arithmeticDeployManages = arithmeticDeployManageRepository.findByEquipmentId(equipmentId);
        return arithmeticDeployManages;
    }

    /**
     * 根据设备id删除算法部署数据
     *
     * @param equipmentId
     */
    public void delByEquipmentId(String equipmentId) {

        List<ArithmeticDeployManage> arithmeticDeployManages = arithmeticDeployManageRepository.findByEquipmentId(equipmentId);
        for (ArithmeticDeployManage arithmeticDeployManage : arithmeticDeployManages) {
            arithmeticDeployManage.setIsValid(0);
            arithmeticDeployManageRepository.save(arithmeticDeployManage);
        }
    }

    /**
     * 根据算法id找到所有的算法部署数据
     *
     * @param id
     * @return
     */
    public List<ArithmeticDeployManage> findDeployById(String id) {
        return arithmeticDeployManageRepository.findByArithmeticId(id);
    }

    /**
     * 删除所有的算法和设备关系
     */
    public void delAllDeploys() {
        arithmeticDeployManageRepository.deleteAll();
    }

    /**
     * 删除指定项目下的算法和设备关系
     *
     * @param projectId
     */
    public void delDeploysById(String projectId) {
        List<EquipmentManage> equipmentManages = equipmentManageService.findByProjectId(projectId);
        for (EquipmentManage equipmentManage : equipmentManages) {
            List<ArithmeticDeployManage> arithmeticDeployManages = arithmeticDeployManageRepository.findByEquipmentId(equipmentManage.getId());
            if (arithmeticDeployManages.size() > 0) {
                arithmeticDeployManageRepository.delete(arithmeticDeployManages);
            }
        }

    }
}
